package com.spzx.cart.service;

import com.spzx.cart.domain.CartInfo;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RemoteProductService remoteProductService;

    private String getCartKey(Long userId) {
        return "user:cart:" + userId;
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        //1.准备cartKey
        //1.1如何获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        //2.判断是否是新增购物车商品，还是修改已有商品数量
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        int thresHold = 99; // 单品上限不能超过99

        if (hashOps.hasKey(skuId.toString())) { //修改已有商品数量
            CartInfo cartInfo = hashOps.get(skuId.toString());
            int totalNum = cartInfo.getSkuNum() + skuNum;
            cartInfo.setSkuNum(totalNum > 99 ? thresHold : totalNum);
            cartInfo.setUpdateTime(new Date());
            hashOps.put(skuId.toString(), cartInfo);
        } else { //不存在则新增购物车商品

            Long size = hashOps.size();
            if (++size > 50) {
                throw new ServiceException("购物车不同商品上限不能超过50");
            }

            //封装购物车商品信息
            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            cartInfo.setCreateTime(new Date());

            R<ProductSku> productSkuResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuResult.getCode()) { //状态码=500说明降级处理了
                throw new ServiceException(productSkuResult.getMsg());
            }
            ProductSku productSku = productSkuResult.getData();

            cartInfo.setCartPrice(productSku.getSalePrice());
            cartInfo.setSkuPrice(productSku.getSalePrice());
            cartInfo.setSkuNum(1); //首次添加默认：1
            cartInfo.setThumbImg(productSku.getThumbImg());
            cartInfo.setSkuName(productSku.getSkuName());
            cartInfo.setIsChecked(1); //默认：1 表示选中状态

            //存放到购物车
            hashOps.put(skuId.toString(), cartInfo);
        }

    }

    @Override
    public List<CartInfo> getCartList() {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //1.获取购物车商品集合
        List<CartInfo> cartInfoList = hashOps.values();

        //2.排序（根据添加购物车时间倒序排序）
        cartInfoList = cartInfoList.stream().sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime())).toList();

        //3.远程调用商品微服务接口，获取多个sku最新商品价格，更新到购物车中。这样在回显购物车信息时，用户可以看到那些商品价格有变动提示。
        if(!CollectionUtils.isEmpty(cartInfoList)){
            List<Long> skuIdList = cartInfoList.stream().map(cartInfo -> cartInfo.getSkuId()).toList();
            R<List<SkuPrice>> skuPriceListResult = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if (R.FAIL == skuPriceListResult.getCode()) {
                throw new ServiceException(skuPriceListResult.getMsg());
            }
            List<SkuPrice> skuPriceList = skuPriceListResult.getData(); //转map类型
            Map<Long, BigDecimal> skuIdToSalePriceMap =
                    skuPriceList.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));

            cartInfoList.forEach(cartInfo -> {
                BigDecimal salePrice = skuIdToSalePriceMap.get(cartInfo.getSkuId());
                cartInfo.setSkuPrice(salePrice);
            });
        }
        //4.返回购物车商品集合
        return cartInfoList;
    }

    @Override
    public void deleteCart(Long skuId) {
        //1.准备cartKey
        //1.1如何获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        //2.删除购物项
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        hashOps.delete(skuId.toString());
    }


    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        //1.准备cartKey
        //1.1如何获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        //2.修改状态
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        if (hashOps.hasKey(skuId.toString())) {
            CartInfo cartInfo = hashOps.get(skuId.toString()); //取
            cartInfo.setIsChecked(isChecked); //改
            hashOps.put(skuId.toString(), cartInfo); //放
        }
    }


    @Override
    public void allCheckCart(Integer isChecked) {
        //1.准备cartKey
        //1.1如何获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        //2.修改状态
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        //3.获取所有的购物车商品集合
        List<CartInfo> cartInfoList = hashOps.values();
        if(!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                cartInfo.setIsChecked(isChecked);
                hashOps.put(cartInfo.getSkuId().toString(),cartInfo);
            }
        }
    }


    @Override
    public void clearCart() {
        //1.准备cartKey
        //1.1如何获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoCheckedList  = new ArrayList<>(); //存放勾选商品


        //1.准备cartKey
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();

        //2.获取打钩商品
        for (CartInfo cartInfo : cartInfoList) {
            if(cartInfo.getIsChecked() == 1){
                cartInfoCheckedList.add(cartInfo);
            }
        }

        return cartInfoCheckedList;
    }

    //购物车价格和实时价格 变成 一致的。
    @Override
    public Boolean updateCartPrice(Long userId) {
        //1.准备cartKey
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if(!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                if(cartInfo.getIsChecked().intValue() == 1){ //只更新购买的购物车商品的最新价格。不买的暂时不更新。
                    // TODO 可以优化处理。
                    R<SkuPrice> skuPriceResult = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER);
                    if(R.FAIL == skuPriceResult.getCode()){
                        throw new ServiceException(skuPriceResult.getMsg());
                    }
                    SkuPrice skuPrice = skuPriceResult.getData();
                    cartInfo.setSkuPrice(skuPrice.getSalePrice());
                    cartInfo.setCartPrice(skuPrice.getSalePrice());

                    hashOps.put(cartInfo.getSkuId().toString(),cartInfo); //更新缓存数据
                }
            }
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        //1.准备cartKey
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if(!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                if(cartInfo.getIsChecked().intValue() == 1){
                    hashOps.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return true;
    }
}
